package com.coursehub.shared.client;

import com.coursehub.shared.dto.ApiResponse;
import com.coursehub.shared.exception.ServiceCallException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * 服务间通信客户端
 */
@Slf4j
@Component
public class ServiceClient {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    // 服务名到URL的映射
    private final Map<String, String> serviceUrls = Map.of(
        "user-management", "http://localhost:8082",
        "course-management", "http://localhost:8083",
        "exercise-management", "http://localhost:8084",
        "learning-progress", "http://localhost:8085"
    );
    
    /**
     * 根据服务名获取完整URL
     */
    private String buildFullUrl(String serviceName, String path) {
        String baseUrl = serviceUrls.get(serviceName);
        if (baseUrl == null) {
            log.warn("Unknown service name: {}, using path as full URL", serviceName);
            return path;
        }
        return baseUrl + path;
    }
    
    /**
     * GET请求
     */
    public <T> T get(String serviceName, String url, Class<T> responseType) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with GET: {}", serviceName, fullUrl);
            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("GET request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "GET request failed", e);
        }
    }
    
    /**
     * GET请求（带参数）
     */
    public <T> T get(String serviceName, String url, Class<T> responseType, Object... uriVariables) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with GET: {}", serviceName, fullUrl);
            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class, uriVariables);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("GET request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "GET request failed", e);
        }
    }
    
    /**
     * POST请求
     */
    public <T> T post(String serviceName, String url, Object request, Class<T> responseType) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with POST: {}", serviceName, fullUrl);
            // 不创建新的headers，让RestTemplate拦截器处理认证headers
            HttpEntity<Object> entity = new HttpEntity<>(request);
            
            ResponseEntity<String> response = restTemplate.postForEntity(fullUrl, entity, String.class);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("POST request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "POST request failed", e);
        }
    }
    
    /**
     * POST请求（带自定义headers）
     */
    public <T> T post(String serviceName, String url, Object request, Class<T> responseType, Map<String, String> customHeaders) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with POST (custom headers): {}", serviceName, fullUrl);
            
            // 创建HttpHeaders并添加自定义headers
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            if (customHeaders != null) {
                customHeaders.forEach(headers::set);
                log.debug("Added custom headers: {}", customHeaders.keySet());
            }
            
            HttpEntity<Object> entity = new HttpEntity<>(request, headers);
            
            ResponseEntity<String> response = restTemplate.postForEntity(fullUrl, entity, String.class);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("POST request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "POST request failed", e);
        }
    }
    
    /**
     * PUT请求
     */
    public <T> T put(String serviceName, String url, Object request, Class<T> responseType) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with PUT: {}", serviceName, fullUrl);
            // 不创建新的headers，让RestTemplate拦截器处理认证headers
            HttpEntity<Object> entity = new HttpEntity<>(request);
            
            ResponseEntity<String> response = restTemplate.exchange(fullUrl, HttpMethod.PUT, entity, String.class);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("PUT request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "PUT request failed", e);
        }
    }
    
    /**
     * DELETE请求
     */
    public <T> T delete(String serviceName, String url, Class<T> responseType) {
        try {
            String fullUrl = buildFullUrl(serviceName, url);
            log.debug("Calling service '{}' with DELETE: {}", serviceName, fullUrl);
            ResponseEntity<String> response = restTemplate.exchange(fullUrl, HttpMethod.DELETE, null, String.class);
            return parseResponse(response, responseType, serviceName);
        } catch (RestClientException e) {
            log.error("DELETE request to service '{}' failed: {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "DELETE request failed", e);
        }
    }
    
    /**
     * 解析响应
     */
    private <T> T parseResponse(ResponseEntity<String> response, Class<T> responseType, String serviceName) {
        try {
            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new ServiceCallException(serviceName, "HTTP " + response.getStatusCode());
            }
            
            String responseBody = response.getBody();
            if (responseBody == null) {
                return null;
            }
            
            // 如果响应类型是String，直接返回
            if (responseType == String.class) {
                return responseType.cast(responseBody);
            }
            
            // 尝试解析为ApiResponse格式
            try {
                ApiResponse<T> apiResponse = objectMapper.readValue(responseBody, 
                    new TypeReference<ApiResponse<T>>() {});
                
                if (apiResponse.getCode() != 200) {
                    throw new ServiceCallException(serviceName, apiResponse.getMessage());
                }
                
                // 如果data为null，返回null
                if (apiResponse.getData() == null) {
                    return null;
                }
                
                // 转换data到目标类型
                return objectMapper.convertValue(apiResponse.getData(), responseType);
            } catch (Exception e) {
                // 如果不是ApiResponse格式，直接解析为目标类型
                return objectMapper.readValue(responseBody, responseType);
            }
            
        } catch (Exception e) {
            log.error("Failed to parse response from service '{}': {}", serviceName, e.getMessage());
            throw new ServiceCallException(serviceName, "Response parsing failed", e);
        }
    }
}